package aws

import (
	"bytes"
	"context"
	"errors"
	"strings"
	"time"

	"github.com/aws/aws-sdk-go-v2/aws"
	"github.com/aws/aws-sdk-go-v2/config"

	aws_notifier "gitee.com/bjf-fhe/apicat/notify/aws"
	"gitee.com/bjf-fhe/apicat/platform"
	"gitee.com/bjf-fhe/apicat/source"
	aws_s3_source "gitee.com/bjf-fhe/apicat/source/aws/s3"
	aliyun_csv_source "gitee.com/bjf-fhe/apicat/source/csv"
	"gitee.com/bjf-fhe/apicat/utils"
	"github.com/extrame/tail"
	"github.com/sirupsen/logrus"
	"github.com/spf13/pflag"
)

type Config struct {
	aws.Credentials
	Dest string
	// AccessKeyId     string
	// AccessKeySecret string
	// SessionToken    string
	regionId     string
	fromDuration string
	tailMode     bool
	interval     string
	cfg          aws.Config
}

func (h *Config) FromMap(m map[string]string) error {
	if v, ok := m["accesskey-id"]; ok {
		h.AccessKeyID = v
	}
	if v, ok := m["accesskey-secret"]; ok {
		h.SecretAccessKey = v
	}
	if v, ok := m["session-token"]; ok {
		h.SessionToken = v
	}
	if v, ok := m["dest"]; ok {
		h.Dest = v
	}
	if v, ok := m["region-id"]; ok {
		h.regionId = v
	}
	if v, ok := m["from"]; ok {
		h.fromDuration = v
	}
	if v, ok := m["interval"]; ok {
		h.interval = v
	}
	return nil
}

func (h *Config) ToMap() map[string]string {
	return map[string]string{
		"accesskey-id":     h.AccessKeyID,
		"accesskey-secret": h.SecretAccessKey,
		"session-token":    h.SessionToken,
		"dest":             h.Dest,
		"region-id":        h.regionId,
		"from":             h.fromDuration,
		"interval":         h.interval,
	}
}

func (h *Config) AddFlags(set *pflag.FlagSet) {
	set.StringVar(&h.AccessKeyID, "accesskey-id", "", "Aws的AccessKeyId")
	set.StringVar(&h.SecretAccessKey, "accesskey-secret", "", "Aws的AccessKeySecret")
	set.StringVar(&h.SessionToken, "session-token", "", "Aws的Session Token")
	set.StringVar(&h.Dest, "dest", "", "写入IPv4规则的目标规则组")
	set.StringVar(&h.regionId, "region-id", "", "需要对接的负载均衡所在Aliyun Region")
	set.StringVar(&h.interval, "interval", "5m", "重复检查日志的时间间隔，AWS日志写入间隔为5分钟，因此默认配置为5m")
	set.StringVar(&h.fromDuration, "from", "", "手工设置日志的起始读取时间，该值传输多长时间之前，比如7d(7天),5h(5小时），3m（3分钟），1s（1秒钟）")
}

func (h *Config) GetNotifier(ctx context.Context) (platform.Notifier, error) {
	var notifier aws_notifier.Handler

	err := notifier.Init(&h.cfg, ctx, h.Dest)
	return &notifier, err
}

func (h *Config) GetSource(fh platform.Configer, ctx context.Context, tailMode bool) (source.Reader, error) {
	h.tailMode = tailMode
	if fh.IsLocalFile() {
		if tailMode {
			//csv mode, csv不支持tail模式
			if strings.HasSuffix(fh.GetFileName(), ".gz") {
				return nil, errors.New("CSV压缩文件读取不支持Tail模式")
			}

			var buf = &bytes.Buffer{}

			var t *tail.Tail

			t, err := tail.TailFile(fh.GetFileName(), tail.Config{Follow: true, Poll: true})

			if err == nil {
				go func() {
					for {
						select {
						case <-ctx.Done():
							t.Stop()
							return
						case line := <-t.Lines:
							buf.Write([]byte(line.Text + "\n"))
						}
					}
				}()
				return aliyun_csv_source.NewReader(buf, ctx, true)
			} else {
				return nil, err
			}

		} else {
			f, err := fh.OpenFile()
			if err == nil {
				return aliyun_csv_source.NewReader(f, ctx, false)
			}
			return nil, err
		}
	} else {
		interval, err := utils.ParseDuration(h.interval)
		if err != nil {
			logrus.Errorln("时间间隔配置错误，使用默认的5分钟间隔")
			interval = 5 * time.Minute
		}
		return aws_s3_source.NewReader(fh.GetFileName(), h.cfg, h.GetFrom(), tailMode, interval)
	}
}

func (h *Config) GetFrom() time.Time {
	return utils.GetTimeFromDuration(h.fromDuration, platform.LOG_INTERVAL, h.tailMode)
}

func (h *Config) Retrieve(ctx context.Context) (aws.Credentials, error) {
	return h.Credentials, nil
}

func (h *Config) Check(fileHandler platform.Configer) error {
	if !fileHandler.IsLocalFile() {

		h.Source = "apicat-global-config"
		if h.AccessKeyID == "" {
			return errors.New("AccessKeyId没有设置，请使用--aws-accesskey-id配置该参数")
		} else {
			logrus.Debugf("您正在使用Aws AccessKey Id：%s进行操作", h.AccessKeyID)
		}

		if h.SecretAccessKey == "" {
			return errors.New("AccessKeySecret没有设置，请使用--aws-accesskey-secret配置该参数")
		}

		if h.regionId == "" {
			return errors.New("Region Id 没有设置，请使用--aws-region-id配置该参数")
		}

		var err error

		h.cfg, err = config.LoadDefaultConfig(context.Background(), config.WithCredentialsProvider(h), config.WithRegion(h.regionId))

		return err
	}
	return nil
}

func init() {
	platform.Register("aws", &Config{})
}
